/**
 * Copyright(c) ${copyrightYear} ${company}
 * All rights reserved.
 * Created on ${date}
 */
package ${package};

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import ${package}.entity.PropertyEntity;
import ${package}.util.ProjectUtil;
import ${package}.util.LogUtil;


/**
 * Property管理对象
 * 
 * @author ${author}
 */
@SuppressWarnings("unchecked")
public final class PropertyManager {
    /**
     * xml配置：不包括的url
     */
    public static final String XML_${artifactId.toUpperCase()}_EXCLUDEAUTHURLS = "${artifactId}/excludeAuthUrls";
    /**
     * xml配置：项目的home目录
     */
    public static final String XML_${artifactId.toUpperCase()}_${artifactId.toUpperCase()}HOME = "${artifactId}/${artifactId}Home";

    /**
     * 存放xml里面属性的集合
     */
    private static Map<String, String> xmlMap = new ConcurrentHashMap<String, String>();
    /**
     * 存放db里面属性的集合
     */
    private static Map<String, String> dbMap = new ConcurrentHashMap<String, String>();
    /**
     * project-config.xml文件
     */
    private static final File PROJECT_CONFIG_FILE = new File(Thread
                    .currentThread().getContextClassLoader().getResource(
                                    "project-config.xml").getFile());
    /**
     * PropertyManager 的单例对象
     */
    private static PropertyManager instance = new PropertyManager();
    
    /**
     * project-config.xml文件的Document对象
     */
    private Document document;


    /**
     * 默认的构造方法
     */
    private PropertyManager(){

    }

    /**
     * 获取PropertyManager对象
     * 
     * @return
     */
    public static PropertyManager getInstance() {
        return instance;
    }

    /**
     * 保存XmlProperties
     */
    private synchronized void saveXmlProperties() {
        // Write data out to a temporary file first.
        Writer writer = null;
        try {
            writer = new BufferedWriter(new OutputStreamWriter(
                            new FileOutputStream(PROJECT_CONFIG_FILE), "UTF-8"));
            OutputFormat prettyPrinter = OutputFormat.createPrettyPrint();
            XMLWriter xmlWriter = new XMLWriter(writer, prettyPrinter);
            xmlWriter.write(document);
        } catch (Exception e) {
            LogUtil.fatal(e.getMessage(), e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e1) {
                    LogUtil.fatal(e1.getMessage(), e1);
                }
            }
        }

    }

    /**
     * 初始化xml的配置文件到该Manager
     * 
     * @throws Exception
     *             所有异常
     */
    public void initXMLConfig() throws Exception {
        SAXReader reader = new SAXReader(false);
        document = reader.read(PROJECT_CONFIG_FILE);

        //${artifactId}/excludeAuthUrls
        Element excludeAuthUrls = (Element) document
                        .selectSingleNode(XML_${artifactId.toUpperCase()}_EXCLUDEAUTHURLS);
        xmlMap.put(XML_${artifactId.toUpperCase()}_EXCLUDEAUTHURLS, excludeAuthUrls.getTextTrim());

        //${artifactId}/${artifactId}Home
        Element homeDir = (Element) document
                        .selectSingleNode(XML_${artifactId.toUpperCase()}_${artifactId.toUpperCase()}HOME);
        xmlMap.put(XML_${artifactId.toUpperCase()}_${artifactId.toUpperCase()}HOME, homeDir.getTextTrim());

    }

    /**
     * 初始化db的数据到该Manager
     * 
     * @throws Exception
     *             所有异常
     */
    public static void initDbProperty() throws Exception {
        EntityManager em = ProjectUtil.getEntityManager();
        try {
            Query query = em
                            .createQuery("from PropertyEntity order by key desc");
            List<PropertyEntity> propertyEntities = query.getResultList();
            for (PropertyEntity propertyEntity : propertyEntities) {
                dbMap.put(propertyEntity.getKey(), propertyEntity.getValue());
            }
        } finally {
            em.close();
        }
    }

    /**
     * 设置数据库的值
     * 
     * @param key
     * @param value
     * @throws Exception
     *             所有异常
     */
    public synchronized void setDBProperty(String key, String value)
                    throws Exception {
        EntityManager em = ProjectUtil.getEntityManager();
        try {
            EntityTransaction transaction = em.getTransaction();
            transaction.begin();
            Query query = em.createQuery("from PropertyEntity where key=:key");
            query.setParameter("key", key);
            PropertyEntity propertyEntity = (PropertyEntity) query.getSingleResult();
            if (propertyEntity == null) {
                return;
            }
            propertyEntity.setValue(value);
            em.merge(propertyEntity);
            transaction.commit();
            dbMap.put(key, value);
        } finally {
            em.close();
        }
    }

    /**
     * 获取数据库的值
     * 
     * @param key
     * @return
     */
    public String getDbProperty(String key) {
        EntityManager em = ProjectUtil.getEntityManager();
        try {
            //先判断dbProperty是否存在，不存在再判断数据库是否存在
            if (dbMap.get(key) == null) {
                Query query = em
                                .createQuery("from PropertyEntity  where key=:key ");
                query.setParameter("key", key);
                PropertyEntity propertyEntity = (PropertyEntity) (query
                                .getSingleResult());
                if (propertyEntity != null) {
                    dbMap.put(key, propertyEntity.getValue());
                }
            }
            return dbMap.get(key);
        } finally {
            em.close();
        }
    }

    /**
     * ，设置xml文件
     * 
     * @param key
     * @param value
     * @throws Exception
     *             所有异常
     */
    public synchronized void setXMLProperty(String key, String value)
                    throws Exception {
        xmlMap.put(key, value);
        Element keyElement = (Element) document.selectSingleNode(key);
        if (keyElement != null) {
            keyElement.setText(value.trim());
            saveXmlProperties();
        }
    }

    /**
     * 获取XML属性
     * 
     * @param key
     * @return
     */
    public synchronized String getXMLProperty(String key) {
        if (xmlMap.get(key) == null) {
            try {
                SAXReader reader = new SAXReader(false);
                    document = reader.read(PROJECT_CONFIG_FILE);
                    Element elementTmp = (Element) document
                                    .selectSingleNode(key);
                    xmlMap.put(key, elementTmp.getTextTrim());
            } catch (DocumentException e) {
                LogUtil.fatal(e);
            }
        }
        return xmlMap.get(key);
    }

}
